
#include "alloc_context_impl.h"
#include "default_settings.h"

#include <stdlib.h>
#include <string.h>

static
QL_ALLOC_GLOBAL_FAILURE_CALLBACK g_failure_callback = 0;

void set_alloc_global_failure_callback( QL_ALLOC_GLOBAL_FAILURE_CALLBACK failure_callback )
{
    g_failure_callback = failure_callback;
}

void alloc_emit_error( AllocContext * c, ErrResult err )
{
    if( 0 != c->failure_callback_p )
    {
        c->failure_callback_p( c, err );
    }

    longjmp( c->failure_jump, err );
}

ErrResult
init_context( AllocContext * c )
{
    int     jmp_ret;

    // init all the context with zeroes
    memset( c, 0, sizeof(AllocContext) );

    jmp_ret = setjmp( c->failure_jump );
    if( jmp_ret != 0 )
    {
        ErrResult     err_result = (ErrResult)jmp_ret;

        // DON'T use any stack variable here since stack frame has destroyed by the moment
        if( 0 != g_failure_callback )
        {
            g_failure_callback( err_result );
        }

        // gracefully kill the application
        assert( !"ql allocator failure happened" );
        exit( -1 );

        return err_result;
    }

    c->impl = ql_mallocz( c, sizeof(AllocContextImpl) );

    apply_default_settings( &c->settings );

    return QL_OK;
}


void free_context( AllocContext * c )
{
    if( 0 != c->impl )
    {
        // free identifiers data
        free_ids_buffers( c );

        // free lists data
        free_lists_buffers( c );

        // free atoms data
        free_atoms_buffers( c );

        // free implementation details' data
        if( 0 != c->impl )
        {
            ql_free( c->impl );
        }
        c->impl = 0;
    }
}
